package com.ruoyi.weiriya.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.WMember;
import com.ruoyi.common.core.domain.entity.WVehicle;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.kit.core.enums.OrderStateEnums;
import com.ruoyi.weiriya.domain.*;
import com.ruoyi.weiriya.domain.enums.GoodsTypeEnum;
import com.ruoyi.weiriya.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.weiriya.mapper.WOrderMapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 用户支付订单Service业务层处理
 * 
 * @author lynn
 * @date 2023-08-01
 */
@Service
public class WOrderServiceImpl extends ServiceImpl<WOrderMapper, WOrder> implements IWOrderService
{
    @Autowired
    private IWMemberService memberService;

    @Autowired
    private IWPayVipRecordService payVipRecordService;

    @Autowired
    private IWMessageService messageService;

    @Autowired
    private IWVipSettingService vipSettingService;

    @Autowired
    private IWVehicleService vehicleService;

    @Autowired
    private IWCompanyService companyService;

    @Autowired
    private IWUserAreaService userAreaService;

    @Autowired
    private WOrderMapper orderMapper;


    @Override
    public void payOrder(String sn, String paymentMethod, String receivableNo) {
        // 更新订单状态
        WOrder wOrder = this.getOne(new LambdaQueryWrapper<WOrder>()
                .eq(WOrder::getSn, sn));
        wOrder.setCompleteTime(new Date());
        wOrder.setPaymentTime(new Date());
        wOrder.setPayOrderNo(receivableNo);
        wOrder.setOrderStatus(OrderStateEnums.PAID.name());
        wOrder.setUpdateBy(wOrder.getCreateBy());
        this.updateById(wOrder);
        // 充值成功后续处理

        // 获取用户信息
        WMember member = memberService.getById(wOrder.getMemberId());

        // 记录会员时间，修改会员相关信息
        String content = successFollowUp(wOrder, member);

        // 发送消息
        sendMsg(member, content);
    }

    private String successFollowUp(WOrder wOrder, WMember member) {
        // 判断类型
        String goodsType = wOrder.getGoodsType();
        // 消息内容
        String content = "";


        // 记录会员时间
        WPayVipRecord vipRecord;
        if(goodsType.equals(GoodsTypeEnum.MONTH_CHARGE.name())){
            vipRecord = new WPayVipRecord();
            vipRecord.setAmount(wOrder.getFinalPrice());
            vipRecord.setVipType(1);
            vipRecord.setType(1);
            // 记录时间
            initAndSaveVipRecord(member, vipRecord, 1);

            content = "充电+停车月卡开通成功！";

            member.setMemberType(1);
            member.setVipType(1);
        } else if(goodsType.equals(GoodsTypeEnum.QUARTER_CHARGE.name())){
            vipRecord = new WPayVipRecord();
            vipRecord.setAmount(wOrder.getFinalPrice());
            vipRecord.setVipType(2);
            vipRecord.setType(1);
            vipRecord.setMemberId(member.getId());
            // 记录时间
            initAndSaveVipRecord(member, vipRecord, 3);

            content = "充电+停车季卡开通成功！";

            member.setMemberType(1);
            member.setVipType(2);
        } else if(goodsType.equals(GoodsTypeEnum.YEAR_CHARGE.name())){
            vipRecord = new WPayVipRecord();
            vipRecord.setAmount(wOrder.getFinalPrice());
            vipRecord.setVipType(3);
            vipRecord.setType(1);
            vipRecord.setMemberId(member.getId());
            // 记录时间
            initAndSaveVipRecord(member, vipRecord, 12);

            content = "充电+停车年卡开通成功！";

            member.setMemberType(1);
            member.setVipType(3);
        } else if(goodsType.equals(GoodsTypeEnum.MONTH_DEPOSIT.name())){
            vipRecord = new WPayVipRecord();
            vipRecord.setAmount(wOrder.getFinalPrice());
            vipRecord.setVipType(1);
            vipRecord.setType(2);
            vipRecord.setMemberId(member.getId());
            // 记录时间
            initAndSaveVipRecord(member, vipRecord, 1);

            content = "停车月卡开通成功！";

            member.setMemberType(2);
            member.setVipType(1);
        } else if(goodsType.equals(GoodsTypeEnum.QUARTER_DEPOSIT.name())){
            vipRecord = new WPayVipRecord();
            vipRecord.setAmount(wOrder.getFinalPrice());
            vipRecord.setVipType(2);
            vipRecord.setType(2);
            vipRecord.setMemberId(member.getId());
            // 记录时间
            initAndSaveVipRecord(member, vipRecord, 3);

            content = "停车季卡开通成功！";

            member.setMemberType(2);
            member.setVipType(2);
        } else if(goodsType.equals(GoodsTypeEnum.YEAR_DEPOSIT.name())){
            vipRecord = new WPayVipRecord();
            vipRecord.setAmount(wOrder.getFinalPrice());
            vipRecord.setVipType(3);
            vipRecord.setType(2);
            vipRecord.setMemberId(member.getId());
            // 记录时间
            initAndSaveVipRecord(member, vipRecord, 12);

            content = "停车年卡开通成功！";

            member.setMemberType(2);
            member.setVipType(3);
        } else if(goodsType.equals(GoodsTypeEnum.WALLET_RECHARGE.name())){
            // 修改用户余额
            Double wallet = member.getWallet();
            Double goodsPrice = wOrder.getGoodsPrice();

            content = "充值成功！充值金额：" + wOrder.getFinalPrice() + "元。";

            member.setWallet(wallet + goodsPrice);
        } else{
            // TODO 记录异常
        }
        // 修改用户信息
        memberService.updateById(member);
        return content;
    }

    private void sendMsg(WMember member, String content) {
        WMessage wMessage = new WMessage();
        wMessage.setUserType(2);
        wMessage.setMessageType(2);
        wMessage.setMessageTitle("会员续费");
        wMessage.setMemberId(member.getId());
        wMessage.setAreaId(member.getAreaId());
        wMessage.setState(1);
        wMessage.setMessageRange(1);
        wMessage.setMessageContent(content);
        wMessage.setCreateBy("1");
        wMessage.setCreateTime(new Date());
        wMessage.setUpdateBy("1");
        wMessage.setUpdateTime(new Date());
        if(StringUtils.isNotBlank(content)) {
            messageService.save(wMessage);
        }
    }

    private void initAndSaveVipRecord(WMember member, WPayVipRecord vipRecord, int months) {
        vipRecord.setMemberId(member.getId());
        Date now = new Date();
        // 获取最近一次记录
        WPayVipRecord oldRecord = payVipRecordService.getOne(new LambdaQueryWrapper<WPayVipRecord>()
                .eq(WPayVipRecord::getMemberId, member.getId())
                .eq(WPayVipRecord::getType, 1)
                .orderByDesc(WPayVipRecord::getCreateTime)
                .last("limit 1"));
        if(StringUtils.isNull(oldRecord) || now.compareTo(oldRecord.getEndTime()) > 0){
            Date date = DateUtils.addDays(DateUtils.addMonths(now, months), 1);
            member.setVipStartTime(now);
            member.setVipEndTime(date);
            // 添加时间
            vipRecord.setStartTime(now);
            vipRecord.setEndTime(date);
        }else{
            // 判断结束时间
            Date endTime = oldRecord.getEndTime();
            vipRecord.setStartTime(endTime);
            vipRecord.setEndTime(DateUtils.addMonths(endTime, months));
            member.setVipEndTime(DateUtils.addMonths(endTime, months));
        }
        // 保存记录
        vipRecord.setCreateBy("1");
        vipRecord.setCreateTime(now);
        vipRecord.setUpdateBy("1");
        vipRecord.setUpdateTime(now);
        payVipRecordService.save(vipRecord);
    }

    @Override
    public WOrder saveOrder(WOrder wOrder) {

        WMember member = SecurityUtils.getLoginUser().getMember();
        if(StringUtils.isNull(member)){
            throw new ServiceException("权限不足！");
        }

        if(StringUtils.isBlank(wOrder.getGoodsType())){
            throw new ServiceException("请选择订单类型！");
        }
        WOrder order = new WOrder();
        // 设置订单号
        order.setSn("sn" + DateUtils.dateTimeNow(DateUtils.YYMMDD) + IdUtil.getSnowflake().nextIdStr());
        // 设置订单类型
        order.setGoodsType(wOrder.getGoodsType());

        member = memberService.getById(member.getId());
        if(StringUtils.isNull(member.getAreaId())){
            throw new ServiceException("请先绑定区域！");
        }

        // 设置订单用户
        order.setMemberId(member.getId());
        // 设置用户类型
        if(member.getVipType() <= 3) {
            order.setMemberType(1);
        } else {
            order.setMemberType(2);
        }
        // 设置订单区域
        order.setAreaId(member.getAreaId());
        order.setPayType(1);

        // 判断用户是否存在未支付的订单
        List<WOrder> list = this.list(new LambdaQueryWrapper<WOrder>()
                .eq(WOrder::getMemberId, member.getId())
                .eq(WOrder::getOrderStatus, OrderStateEnums.UNPAID.name()));
        if(list.size() >= 1){
            throw new ServiceException("存在待支付的订单！");
        }

        // 分类处理
        String goodsType = wOrder.getGoodsType();
        if(goodsType.equals(GoodsTypeEnum.MONTH_CHARGE.name())){
            initPrice(member, order, 1, 1, true);
        } else if(goodsType.equals(GoodsTypeEnum.QUARTER_CHARGE.name())){
            initPrice(member, order, 1, 3, true);
        } else if(goodsType.equals(GoodsTypeEnum.YEAR_CHARGE.name())){
            initPrice(member, order, 1, 12, true);
        } else if(goodsType.equals(GoodsTypeEnum.MONTH_DEPOSIT.name())){
            initPrice(member, order, 2, 1, false);
        } else if(goodsType.equals(GoodsTypeEnum.QUARTER_DEPOSIT.name())){
            initPrice(member, order, 2, 3, false);
        } else if(goodsType.equals(GoodsTypeEnum.YEAR_DEPOSIT.name())){
            initPrice(member, order, 2, 12, false);
        } else if(goodsType.equals(GoodsTypeEnum.WALLET_RECHARGE.name())){
            Double goodsPrice = wOrder.getGoodsPrice();
            if(StringUtils.isNull(goodsPrice) || goodsPrice <= 0 || goodsPrice > 99999999.99){
                throw new ServiceException("请填写合理的金额！允许范围：0.01-99999999.99");
            }
            order.setGoodsPrice(goodsPrice);
            order.setFinalPrice(goodsPrice);
        } else{
            throw new ServiceException("订单类型不存在！");
        }

        // 设置订单状态
        order.setOrderStatus(OrderStateEnums.UNPAID.name());
        order.setCreateTime(new Date());

        // 保存订单
        this.save(order);

        return order;
    }

    private void initPrice(WMember member, WOrder order, int settingType, int months, Boolean isCharge) {
        // 获取用户车辆
        WVehicle vehicle = vehicleService.getOne(new LambdaQueryWrapper<WVehicle>()
                .eq(WVehicle::getMemberId, member.getId()));
        if(StringUtils.isNull(vehicle)){
            throw new ServiceException("未绑定车辆，请联系管理员绑定车辆！");
        }
        // 获取价格
        WVipSetting vipSetting;
        if(isCharge) {
            vipSetting = vipSettingService.getOne(new LambdaQueryWrapper<WVipSetting>()
                    .eq(WVipSetting::getSettingType, settingType)
                    .eq(WVipSetting::getAreaId, member.getAreaId())
                    .eq(WVipSetting::getVehicleType, vehicle.getVehicleChargeTypeId()));
        } else {
            vipSetting = vipSettingService.getOne(new LambdaQueryWrapper<WVipSetting>()
                    .eq(WVipSetting::getSettingType, settingType)
                    .eq(WVipSetting::getAreaId, member.getAreaId())
                    .eq(WVipSetting::getVehicleType, vehicle.getVehicleNonChargeTypeId()));
        }
        if(StringUtils.isNull(vipSetting)){
            throw new ServiceException("该区域未设置价格，请联系管理员！");
        }
        Double amount = 999D;
        if(months == 1){
            amount = vipSetting.getMonthAmount();
        } else if(months == 3){
            amount = vipSetting.getQuarterAmount();
        } else if(months == 12){
            amount = vipSetting.getYearAmount();
        }
        // 设置订单价格
        order.setGoodsPrice(amount);
        order.setFinalPrice(amount);
    }

    @Override
    public List<WOrder> getList(WOrder wOrder) {
        String openId = SecurityUtils.getLoginUser().getOpenId();
        List<WOrder> list;
        if(StringUtils.isNotBlank(openId)){
            list = this.list(new LambdaQueryWrapper<WOrder>()
                    .eq(WOrder::getMemberId, SecurityUtils.getUserId())
                    .eq(StringUtils.isNotNull(wOrder.getMemberType()), WOrder::getMemberType, wOrder.getMemberType())
                    .eq(StringUtils.isNotBlank(wOrder.getOrderStatus()), WOrder::getOrderStatus, wOrder.getOrderStatus())
                    .orderByDesc(WOrder::getCreateTime));
        } else {
            // 获取管理员的所有区域ID
            QueryWrapper<WOrder> queryWrapper = wOrder.queryWrapper();
            if (StringUtils.isNotBlank(SecurityUtils.getLoginUser().getUser().getCompanyId())) {
                List<String> areaIdListByUserId = companyService.getAreaIdList();
                if(areaIdListByUserId.size() > 0) {
                    queryWrapper.in("o.area_id", areaIdListByUserId);
                } else {
                    return new ArrayList<>();
                }
            }
            list = orderMapper.getList(queryWrapper);
        }
        for (WOrder order : list) {
            order.setOrderType(GoodsTypeEnum.getEnumValue(wOrder.getGoodsType()));
        }
        return list;
    }

    @Override
    public WOrder getWOrderById(String id) {
        WOrder wOrder = orderMapper.getWOrderById(id);
        wOrder.setOrderType(GoodsTypeEnum.getEnumValue(wOrder.getGoodsType()));
        return wOrder;
    }

    @Override
    public boolean cancel(WOrder wOrder) {
        Long userId = SecurityUtils.getUserId();
        WOrder byId = this.getById(wOrder.getId());
        if(StringUtils.isNull(byId)){
            throw new ServiceException("订单不存在！");
        }
        if(!byId.getMemberId().equals(userId.toString())){
            throw new ServiceException("权限不足！");
        }
        if(!byId.getOrderStatus().equals(OrderStateEnums.UNPAID.name())){
            throw new ServiceException("订单不可取消！");
        }
        byId.setOrderStatus(OrderStateEnums.CANCEL.name());
        byId.setCancelReason("用户取消！");
        byId.setCompleteTime(new Date());
        return this.updateById(byId);
    }

    @Transactional
    @Override
    public boolean updateWOrderById(WOrder wOrder) {
        WOrder order = this.getById(wOrder.getId());
        if(StringUtils.isNull(order)){
            throw new ServiceException("订单不存在！");
        }
        if(!order.getOrderStatus().equals(OrderStateEnums.UNPAID.name())){
            throw new ServiceException("订单不可改价！");
        }
        Double finalPrice = wOrder.getFinalPrice();
        if(StringUtils.isNull(finalPrice) || finalPrice < 0D || finalPrice > order.getGoodsPrice()){
            throw new ServiceException("请填写合理的金额！(0-" + order.getGoodsPrice() + ")");
        }
        List<String> list = companyService.getAreaIdList();
        if (!SecurityUtils.getLoginUser().isAdministrators() || !list.contains(order.getAreaId())) {
            throw new ServiceException("权限不足！");
        }
        // 当价格修改为0时， 直接完成订单
        if(finalPrice == 0D){
            // 修改订单信息
            order.setCompleteTime(new Date());
            order.setPaymentTime(new Date());
            order.setPayOrderNo("-1");
            order.setOrderStatus(OrderStateEnums.PAID.name());
            this.updateById(wOrder);

            // 充值成功后续处理
            // 获取用户信息
            WMember member = memberService.getById(wOrder.getMemberId());

            // 记录会员时间，修改会员相关信息
            String content = successFollowUp(wOrder, member);

            // 发送消息
            sendMsg(member, content);
        }

        order.setFinalPrice(wOrder.getFinalPrice());
        order.setChangePriceUserId(SecurityUtils.getUserId().toString());
        return this.updateById(order);
    }

    @Override
    public void orderTimeoutTask() {

        Date date = DateUtils.addMinutes(new Date(), -30);
        String dateStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, date);
        List<WOrder> list = this.list(new LambdaQueryWrapper<WOrder>()
                .eq(WOrder::getOrderStatus, OrderStateEnums.UNPAID.name())
                .le(WOrder::getCreateTime, dateStr));
        System.out.println("订单超时进来了");
        if(list.size() > 0) {
            for (WOrder wOrder : list) {
                System.out.println(wOrder.getSn() + "超时了");
                // 修改订单信息
                wOrder.setCompleteTime(new Date());
                wOrder.setOrderStatus(OrderStateEnums.CANCEL.name());
                wOrder.setCancelReason("超时自动取消");
            }
            this.updateBatchById(list);
        }
    }
}
